package top.archiesean.common.log.aspect;


import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import top.archiesean.common.core.utils.context.SpringContextUtil;
import top.archiesean.common.core.utils.gson.GsonUtil;

import top.archiesean.common.log.annotation.SysLog;
import top.archiesean.common.log.properties.LogProperties;


import java.util.Map;
import java.util.Objects;

/**
 * @author ArchieSean
 * @description 操作日志切面
 * @date 2024-02-18 14:00
 */
@Slf4j
@Aspect
@RequiredArgsConstructor
public class SysLogAspect {

    @Around("@annotation(sysLog)")
    @SneakyThrows
    public Object around(ProceedingJoinPoint point, SysLog sysLog) {
        String strClassName = point.getTarget().getClass().getName();
        String strMethodName = point.getSignature().getName();

        String value = sysLog.value();
        log.info("[类名]:{},[方法]:{},方法描述: {}", strClassName, strMethodName, value);

        HttpServletRequest request = ((ServletRequestAttributes) Objects
                .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        //获取请求ip
        String ip = JakartaServletUtil.getClientIP(request);
        //uri
        String uri = URLUtil.getPath(request.getRequestURI());
        //请求方式
        String method = request.getMethod();
        //get参数脱敏
        LogProperties logProperties = SpringContextUtil.getBean(LogProperties.class);
        Map<String, String[]> paramsMap = MapUtil.removeAny(request.getParameterMap(),
                ArrayUtil.toArray(logProperties.getExcludeFields(), String.class));
        //开始时间
        long startTime = System.currentTimeMillis();
        Object obj;
        try {
            obj = point.proceed();
        } finally {
            //结束时间
            long endTime = System.currentTimeMillis();
            log.info("请求ip: 【{}】,请求路径:【{}】,请求方式【{}】,请求耗时：【{}】ms,请求参数：【{}】",
                    ip, uri, method, endTime - startTime, StrUtil.subPre(GsonUtil.toGsonString(paramsMap),
                            logProperties.getMaxLength()));
        }
        return obj;
    }
}
